package com.woniu.stafforder.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alipay.api.AlipayApiException;
import com.woniu.common.util.ResponseData;
import com.woniu.common.util.ResponseEnum;
import com.woniu.stafforder.dto.ChangeChildrenOrderStateDto;
import com.woniu.stafforder.dto.OrderMainDto;
import com.woniu.stafforder.entity.Order;
import com.woniu.stafforder.service.OrderDetailService;
import com.woniu.stafforder.service.OrderService;
import com.woniu.stafforder.service.PayService;
import com.woniu.stafforder.util.AlipayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Service
@Transactional(propagation = Propagation.SUPPORTS,
        isolation = Isolation.DEFAULT, timeout = 2000,
        readOnly = true, rollbackFor = RuntimeException.class
)
@Slf4j
public class PayServieImpl implements PayService {
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderDetailService orderDetailService;
    private static final String REDIS_ORDER_MAIN_DTO = "orderMainDto:";

    @Override
    public String getPayHtml(String orderNum) {
        try {
            Order order = orderService.lambdaQuery().eq(Order::getID, orderNum).one();
            if (ObjectUtil.isEmpty(order)) {
                return null;
            }
            return AlipayUtil.createHtml(order.getID().toString(), order.getPayPrice());
        } catch (AlipayApiException e) {
            log.error("创建支付宝二维码异常：{}", e.toString());
            return null;
        }
    }

    @Override
    public ResponseData<?> refund(String orderNumStr) {
        try {
            long orderNum = Long.parseLong(orderNumStr);
            List<Long> idList = new ArrayList<>();
            // 检测orderNum是不是子订单
            Long mainOrderNum = orderDetailService.queryMainOrderNumByChildId(orderNum);

            // 是子订单
            if (ObjectUtil.isNotEmpty(mainOrderNum)) {
                idList = new ArrayList<>();
                idList.add(orderNum);
                orderNum = mainOrderNum;
            }
            // 查询订单
            ResponseData<?> responseData = orderService.queryOrderByOrderNum(orderNum);
            OrderMainDto orderMainDto = (OrderMainDto) responseData.getData();
            if (ObjectUtil.isEmpty(orderMainDto)) {
                return new ResponseData<>().fail("退款失败");
            }
            // 获取订单类型id
            Integer typeId = orderMainDto.getTypeId();

            if (ObjectUtil.isEmpty(mainOrderNum)) {
                idList = orderMainDto.getIdList();
            }
            BigDecimal totalPayMoney = orderDetailService.queryTotalPayMoneyById(idList);
            // 退款状态
            boolean refund = AlipayUtil.refund(orderNumStr, totalPayMoney);

            if (refund) {
                log.info("支付宝退款成功");
            } else {
                log.info("支付宝退款失败或无此订单");
            }

            switch (typeId) {
                case 1:
                    refundChangeState(orderNum, idList, 7, 5);
                    break;
                case 2:
                    refundChangeState(orderNum, idList, 116, 115);
                    break;
                case 3:
                    refundChangeState(orderNum, idList, 211, 210);
                    break;
                case 4:
                    refundChangeState(orderNum, idList, 308, 307);
                    break;
                case 5:
                    refundChangeState(orderNum, idList, 506, 506);
                    break;
                default:
            }
            return new ResponseData<>().ok();
        } catch (AlipayApiException e) {
            log.error("支付宝退款异常：{}", e.toString());
            return new ResponseData<>().fail(ResponseEnum.FAIL);
        }
    }

    @Override
    public void paySuccess(String orderNumStr) {
        long orderNum = Long.parseLong(orderNumStr);

        ResponseData<?> responseData = orderService.queryOrderByOrderNum(orderNum);
        OrderMainDto orderMainDto = (OrderMainDto) responseData.getData();

        // 获取订单类型id
        Integer typeId = orderMainDto.getTypeId();
        List<Long> idList = orderMainDto.getIdList();

        switch (typeId) {
            case 1:
                payChangeState(orderNum, idList, 4);
                break;
            case 2:
                payChangeState(orderNum, idList, 108);
                break;
            case 3:
                payChangeState(orderNum, idList, 207);
                break;
            case 4:
                payChangeState(orderNum, idList, 304);
                break;
            case 5:
                payChangeState(orderNum, idList, 503);
                break;
            default:
        }
    }

    /**
     * 支付成功改状态
     *
     * @param orderNum
     * @param idList
     * @param status
     */
    private void payChangeState(Long orderNum, List<Long> idList, Integer status) {
        orderService.lambdaUpdate().eq(Order::getID, orderNum).set(Order::getStatus, status).update();

        ChangeChildrenOrderStateDto changeChildrenOrderStateDto = new ChangeChildrenOrderStateDto();
        changeChildrenOrderStateDto.setIdList(idList);
        changeChildrenOrderStateDto.setStatus(status);
        orderDetailService.updateChildrenOrderStatus(changeChildrenOrderStateDto);
    }

    /**
     * 退款
     *
     * @param orderNum
     * @param idList
     * @param mainStatus
     * @param childStatus
     */
    private void refundChangeState(Long orderNum, List<Long> idList, Integer mainStatus, Integer childStatus) {
        orderService.lambdaUpdate().eq(Order::getID, orderNum).set(Order::getStatus, mainStatus).update();

        ChangeChildrenOrderStateDto changeChildrenOrderStateDto = new ChangeChildrenOrderStateDto();
        changeChildrenOrderStateDto.setIdList(idList);
        changeChildrenOrderStateDto.setStatus(childStatus);
        orderDetailService.updateChildrenOrderStatus(changeChildrenOrderStateDto);
    }

}
